package com.ys.service.hr.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.ys.entity.sys.YsProcInst;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.finance.TcwWanliOtherPaymentItem;
import com.ys.entity.flow.YspModel;
import com.ys.entity.hr.ThrOperateCompanyApply;
import com.ys.entity.hr.ThrTransparencyProgram;
import com.ys.entity.hr.ThrTransparencyProgramItem;
import com.ys.entity.sys.TsUserChange;
import com.ys.entity.sys.YsCol;
import com.ys.entity.sys.YsMenu;
import com.ys.enume.finance.PaymentEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.mapper.hr.ThrTransparencyProgramItemMapper;
import com.ys.mapper.hr.ThrTransparencyProgramMapper;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.flow.YspTaskService;
import com.ys.service.hr.ThrTransparencyProgramService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;

/**
 * 透明计划申报
 */
@Service("thrTransparencyProgramService")
public class ThrTransparencyProgramServiceImpl implements ThrTransparencyProgramService {

	@Autowired
	private ThrTransparencyProgramMapper thrTransparencyProgramMapper;
	
	@Autowired
	private ThrTransparencyProgramItemMapper thrTransparencyProgramItemMapper;


	@Autowired
	private YspTaskService yspTaskService;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;



	/**
	 * 新增透明计划申报
	 * @param params
	 * @param subData
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R add(Map<String, Object> params, String subData) throws Exception {
		//验证
		String msg = yzMsg(params);
		if (msg != null){
			return R.error(msg);
		}
		ThrTransparencyProgram thrTransparencyProgram = JSON.parseObject(JSON.toJSONString(params), ThrTransparencyProgram.class);
		if (new ThrTransparencyProgram().setBid(thrTransparencyProgram.getBid()).count() != 0){
			return R.error("该单号已存在，核实后再操作!");
		}

		// 验证是否有详情数据
		JSONArray detailJA = JSON.parseArray(subData);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		String loginUserId = ShiroUtils.getUserId();
		TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();

		thrTransparencyProgram.setStatus(0);
		thrTransparencyProgram.setCreateChangeId(String.valueOf(tsUserChange.getId()));
		thrTransparencyProgram.setEffectStock(FlowEnum.EffectStock.NOT_EFFECT.value);
		thrTransparencyProgramMapper.insert(thrTransparencyProgram);
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			if(detailJO.get("vgsbm") == null){
				throw new RuntimeException("运营公司不能为空,不允许保存!");
			}
			if(detailJO.get("platformCode") == null){
				throw new RuntimeException("平台服务不能为空,不允许保存!");
			}
			if(detailJO.get("billingMonth") == null){
				throw new RuntimeException("账单月份不能为空,不允许保存!");
			}
			if(detailJO.get("billingAmount") == null){
				throw new RuntimeException("账单金额不能为空,不允许保存!");
			}else {
				Pattern pattern = Pattern.compile("\\d+(\\.\\d{1,2})?");
				Matcher matcher = pattern.matcher(detailJO.get("billingAmount").toString());
				if (!matcher.matches()){
					throw new RuntimeException("金额输入有误,不允许保存!");
				}
			}
			if(detailJO.get("platformBid") == null){
				throw new RuntimeException("平台服务单号不能为空,不允许保存!");
			}
			ThrTransparencyProgramItem thrTransparencyProgramItem = JSON.parseObject(JSON.toJSONString(detailJO), ThrTransparencyProgramItem.class);
			thrTransparencyProgramItem.setTransparencyProgramBid(thrTransparencyProgram.getBid());
			//运营编码和月份 每个月只能有一条
			if (new ThrTransparencyProgramItem().setVgsbm(thrTransparencyProgramItem.getVgsbm()).setBillingMonth(thrTransparencyProgramItem.getBillingMonth())
					.addLeftJoin("THR_TransparencyProgram B ON B.bid = A.transparencyProgramBid")
					.where("B.effectStock != 2")
					.count() != 0){
				throw new RuntimeException("运营公司:"+ thrTransparencyProgramItem.getVgsbm()+",再该账单月份"+thrTransparencyProgramItem.getBillingMonth()+"已制单,不允许保存!");
			}
			thrTransparencyProgramItem.setStatePay(PaymentEnum.StatePay.INIT.value);
			thrTransparencyProgramItemMapper.insert(thrTransparencyProgramItem);
		}


		YsMenu ysMenu = new YsMenu().setId(MenuId.THR_TransparencyProgram).queryFirst();
		if (ysMenu.getFlowModelId().longValue() != 0L) {
			YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
			String codeModel = yspModel.getCode();
			String createUserId = ShiroUtils.getUserId();
			yspTaskService.init(codeModel, thrTransparencyProgram.getBid(), createUserId);
		}

		return R.ok(AddDto.gotoEdit("/web/hr/thrTransparencyProgram/toEdit?bid=" + thrTransparencyProgram.getBid()));
	}

	/**
	 * 修改透明计划申报
	 * @param params
	 * @param subData
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R edit(Map<String, Object> params, String subData) throws Exception {
		//验证
		String msg = yzMsg(params);
		if (msg != null){
			return R.error(msg);
		}
		ThrTransparencyProgram thrTransparencyProgram = JSON.parseObject(JSON.toJSONString(params), ThrTransparencyProgram.class);
		if (new ThrTransparencyProgram().setBid(thrTransparencyProgram.getBid()).where("A.id != " + thrTransparencyProgram.getId()).count() != 0){
			return R.error("该单号已存在，核实后再操作!");
		}

		// 验证是否有详情数据
		JSONArray detailJA = JSON.parseArray(subData);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		//判断是否实在制单中
		Integer flowState = yspTaskService.flowState(thrTransparencyProgram.getBid());

		if (flowState != 0){
			return R.error("透明计划申报单不是制单中,不允许保存!");
		}

		thrTransparencyProgramMapper.update(thrTransparencyProgram);


		List<ThrTransparencyProgramItem> thrTransparencyProgramItemListNew = new ArrayList<>();
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			if(detailJO.get("vgsbm") == null){
				throw new RuntimeException("运营公司不能为空,不允许保存!");
			}
			if(detailJO.get("platformCode") == null){
				throw new RuntimeException("平台服务不能为空,不允许保存!");
			}
			if(detailJO.get("billingMonth") == null){
				throw new RuntimeException("账单月份不能为空,不允许保存!");
			}
			if(detailJO.get("billingAmount") == null){
				throw new RuntimeException("账单金额不能为空,不允许保存!");
			}else {
				Pattern pattern = Pattern.compile("\\d+(\\.\\d{1,2})?");
				Matcher matcher = pattern.matcher(detailJO.get("billingAmount").toString());
				if (!matcher.matches()){
					throw new RuntimeException("金额输入有误,不允许保存!");
				}
			}
			if(detailJO.get("platformBid") == null){
				throw new RuntimeException("平台服务单号不能为空,不允许保存!");
			}
			ThrTransparencyProgramItem thrTransparencyProgramItem = JSON.parseObject(JSON.toJSONString(detailJO), ThrTransparencyProgramItem.class);
			thrTransparencyProgramItem.setTransparencyProgramBid(thrTransparencyProgram.getBid());
			//运营编码和月份 每个月只能有一条
			if (new ThrTransparencyProgramItem().setVgsbm(thrTransparencyProgramItem.getVgsbm()).setBillingMonth(thrTransparencyProgramItem.getBillingMonth())
					.addLeftJoin("THR_TransparencyProgram B ON B.bid = A.transparencyProgramBid")
					.where(" B.effectStock != 2 AND A.id != " + thrTransparencyProgramItem.getId()).count() != 0){
				throw new RuntimeException("运营公司:"+ thrTransparencyProgramItem.getVgsbm()+",再该账单月份"+thrTransparencyProgramItem.getBillingMonth()+"已制单,不允许保存!");
			}
			if (thrTransparencyProgramItem.getId() == null){
				thrTransparencyProgramItem.setStatePay(PaymentEnum.StatePay.INIT.value);
				thrTransparencyProgramItemMapper.insert(thrTransparencyProgramItem);
			}else {
				thrTransparencyProgramItemMapper.update(thrTransparencyProgramItem);
			}
			thrTransparencyProgramItemListNew.add(thrTransparencyProgramItem);
		}

		//删除
		List<ThrTransparencyProgramItem> thrTransparencyProgramItemOld = new ThrTransparencyProgramItem().setTransparencyProgramBid(thrTransparencyProgram.getBid()).queryList();
		for (ThrTransparencyProgramItem thrTransparencyProgramItem :thrTransparencyProgramItemOld){
			List<ThrTransparencyProgramItem> thrTransparencyProgramItemNewO = thrTransparencyProgramItemListNew.stream()
					.filter(thrTransparencyProgramItemNew -> thrTransparencyProgramItemNew.getId().equals(thrTransparencyProgramItem.getId())).collect(Collectors.toList());
			if (thrTransparencyProgramItemNewO.size() == 0){
				thrTransparencyProgramItemMapper.deleteTrue(thrTransparencyProgramItem.getId());
			}
		}

		return R.ok(AddDto.gotoEdit("/web/hr/thrTransparencyProgram/toEdit?bid=" + thrTransparencyProgram.getBid()));
	}

	/**
	 * 删除透明计划申报
	 * @param id 主键id
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R del(Long id) throws Exception {
		ThrTransparencyProgram thrTransparencyProgram = new ThrTransparencyProgram().setId(id).queryFirst();
		if (thrTransparencyProgram == null){
			throw new RuntimeException("透明计划申报单据不存在,请核实后再操作!");
		}

		//判断是否实在制单中
		Integer flowState = yspTaskService.flowState(thrTransparencyProgram.getBid());

		if (flowState != 0){
			throw new RuntimeException("透明计划申报单不是制单中,不允许删除!");
		}

		if (thrTransparencyProgram.getStatus() != 1 && thrTransparencyProgram.getStatus() != 0){
			throw new RuntimeException("透明计划申报单已被万里汇外币付款单使用,不允许删除!");
		}

		yspTaskService.flowDelete(thrTransparencyProgram.getBid(),thrTransparencyProgram.getCreateChangeId());

		thrTransparencyProgramMapper.deleteTrue(id);

		List<ThrTransparencyProgramItem> thrTransparencyProgramItems = new ThrTransparencyProgramItem().setTransparencyProgramBid(thrTransparencyProgram.getBid()).queryList();
		for (ThrTransparencyProgramItem thrTransparencyProgramItem : thrTransparencyProgramItems){
			thrTransparencyProgramItemMapper.deleteTrue(thrTransparencyProgramItem.getId());
		}
		return R.ok("删除成功!");
	}


	/**
	 * 透明计划申报流转
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R flowPass(String bid, String loginUserId) throws Exception {
		try {
			Flow f = yspTaskService.flowPass(bid, loginUserId);
			if (f.getCode() == Flow.Code.FAILED.value) {
				return R.error(f.getMsg());
			} else {
				if (f.getState() == Flow.State.FINISH.value) {
		    		ThrTransparencyProgram entity = new ThrTransparencyProgram().setBid(bid).queryFirst();
					R r = flowFinish(entity);
					if (r.getCode() == 1) {
						return R.error(r.getMsg());
					}

				}
				return R.ok();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("透明计划申报流转失败!");
		}
	}

	public R flowFinish(ThrTransparencyProgram entity) throws Exception {
		entity.setEffectStock(1);
		thrTransparencyProgramMapper.update(entity);

		List<ThrTransparencyProgramItem> thrTransparencyProgramItemList =  new ThrTransparencyProgramItem().setTransparencyProgramBid(entity.getBid()).queryList();
		for (ThrTransparencyProgramItem thrTransparencyProgramItem : thrTransparencyProgramItemList){
			//划出公司
			ThrOperateCompanyApply thrOperateCompanyApply = new ThrOperateCompanyApply().setVgsbm(thrTransparencyProgramItem.getVgsbm()).queryFirst();

			//客服部
			ThrOperateCompanyApply thrOperateCompanyApplyKf = new ThrOperateCompanyApply().setVgsbm("GS0614").queryFirst();
			if (thrOperateCompanyApplyKf == null){
				throw new RuntimeException("客服部公司资金账户不存在!");
			}

			//划出
			/**
			 * 新增一条流水
			 * 必填：vgsbm划出公司编码；vgsbmp划入公司编码；vjylx交易类型；fje交易金额；djysj交易时间；dshsj审核时间；vbz备注
			 * 选填：mname;mtype;mnid;mbid;mguid；writeTime记账时间（如果为空，默认审核时间）
			 */
			R r = tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyNoTrigger(
					thrOperateCompanyApply.getVgsbm(), thrOperateCompanyApplyKf.getVgsbm(),
					TransactionTypeEnum.BusinessType.THR_TransparencyProgram.name, new BigDecimal(10).negate(), entity.getCreateTime(), new Date(),
					"透明计划申请：单号" + entity.getBid() + ",账单月份:" + thrTransparencyProgramItem.getBillingMonth() + ",透明计划代缴手续费:",
					entity.getBid(),null);
			if (r.getCode() == 1){
				throw new RuntimeException(r.getMsg());
			}

			//划入
			R r1 = tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyNoTrigger(
					thrOperateCompanyApplyKf.getVgsbm(), thrOperateCompanyApply.getVgsbm(),
					TransactionTypeEnum.BusinessType.THR_TransparencyProgram.name, new BigDecimal(10), entity.getCreateTime(), new Date(),
					"透明计划申请：单号" + entity.getBid() + ",账单月份:" + thrTransparencyProgramItem.getBillingMonth() + ",透明计划代缴手续费:",
					entity.getBid(),null);

			if (r1.getCode() == 1){
				throw new RuntimeException(r1.getMsg());
			}
		}

		return R.ok();
	}



	private String yzMsg(Map<String, Object> infoMap){
		//验证导入字段
		String backMsg = "";
		//获取pc字段数据
		List<YsCol> listField = new YsCol()
				.where("A.MenuId = "+ MenuId.THR_TransparencyProgram)
				.setOrderby("A.SortNo ASC")
				.queryList();
		//验证必填字段的非空；其他字段的长度限制、类型
		try {
			backMsg = checkUtil.checkTableColLengthAndDataType(
					"THR_TransparencyProgram",
					listField,
					infoMap,
					ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1
			);
			if(backMsg!=null && !"".equals(backMsg)){//若有误，则跳过这条信息
				return backMsg;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}


	@Override
	public R cancel(String bid,Long id) {
		if (bid == null || bid.length() == 0) {
			return R.error("ID不能为空!");
		}

		ThrTransparencyProgram entity = new ThrTransparencyProgram().setBid(bid).queryFirst();
		if (entity.getEffectStock() != FlowEnum.EffectStock.EFFECTED.value) {
			return R.error("未生效数据无法作废!");
		}
		//是否被外币付款单使用
		int count = new TcwWanliOtherPaymentItem().setRelativeId(id)
				.addLeftJoin("TCW_WanliOtherPayment B on B.Bid = A.Pbid")
				.where("B.PayType = 1")
				.count();
		if (count != 0){
			return R.error("该数据已经被外币付款单使用,无法作废!");
		}
		 count = new ThrTransparencyProgramItem().setTransparencyProgramBid(bid).setStatePay(2)
				.count();
		if (count != 0){
			return R.error("该数据已缴纳,无法作废!");
		}

		// 作废主数据
		entity.setEffectStock(FlowEnum.EffectStock.CANCELD.value);
		thrTransparencyProgramMapper.update(entity);
		return R.ok();
	}

	//获取列表数据
	@Override
	@Transactional
	public Map<String,Object> getExtraParam( String bid) throws Exception{

		Map<String, Object> entity = new ThrTransparencyProgram().setBid(bid).queryFirstMap();

		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();

		entity.put("updateTime1", DateUtil.getYYYY_MM_DD_HH_mm_ss(ysProcInst.getUpdateTime()));
		return entity;
	}
	//获取子列表数据
	@Override
	@Transactional
	public List<Map<String, Object>> getItemList( String bid) throws Exception{
		List<Map<String, Object>> sonlist = new ThrTransparencyProgramItem()
				.setTransparencyProgramBid(bid)
				.addLeftJoin("TB_PlatformServicePayAccount tpsa ON  tpsa.id = A.ptId")//平台付款管理
				.addField("tpsa.vyhzhmc AS vyhzhmc,tpsa.vkhh AS vkhh,tpsa.achRouting AS achRouting,tpsa.vyhzh AS vyhzh,tpsa.swiftCode AS swiftCode,tpsa.serviceName AS serviceName")
				.addLeftJoin("TP_AmazonShopExchangeRate ter ON  ter.id = tpsa.AmazonShopExchangeRateld")//币种管理
				.addField("ter.code AS exchangeRateCode")
				.addLeftJoin("THR_OperateCompanyApply toca ON  toca.vgsbm = A.vgsbm")//运营公司
				.addField("toca.vgsbm AS vgsbm,toca.vgsjc AS vgsjc")
				.queryMap();
		return sonlist;
	}



}
